<template>
  <div class="wrapper">
    <div class="title">
      <i class="iconfont icon-jiantou_liebiaoshouqi" @click="backPrevPath"></i>
      <span class="path">{{ queryParam.selectPath }}</span>
    </div>

    <div class="content">
      <div class="left" v-loading="contentLoading">
        <FileTable :files="files" @selection-change="handleSelectionChange" @dblClickPath="handleDblClickPath" />
      </div>

      <div class="right">
        <div class="fun-block">
          <div class="fun-title">
            文件查询
            <el-tag>{{ files.length }}</el-tag>
          </div>

          <el-input placeholder="请选择一个目录位置" size="default" v-model="queryParam.selectPath"> </el-input>
          <el-button type="primary" size="default" @click="openDir">
            <i class="iconfont icon-dakaiwenjianjia"></i>&nbsp; 选择
          </el-button>

          <el-input placeholder="请输入需要搜索的文件名" size="default" v-model="queryParam.input"> </el-input>
          <el-button
            type="primary"
            size="default"
            :disabled="!queryParam.input"
            @click="search"
            :loading="contentLoading"
          >
            <i class="iconfont icon-fangdajing" v-if="!contentLoading">&nbsp;</i>
            搜索
          </el-button>

          <div class="menu">
            <div class="menu-item">
              <el-checkbox v-model="queryParam.isDeep" border size="small">递归</el-checkbox>
            </div>

            <div class="menu-item">
              <el-checkbox v-model="queryParam.isReg" border size="small">正则匹配</el-checkbox>
              <i class="iconfont icon-bangzhu" @click="shellOpen('https://docs.rs/regex/latest/regex/#syntax')"></i>
            </div>

            <div class="menu-item">
              <span>查询类型: </span>
              <el-select v-model="queryParam.searchType" placeholder="选择查询类型" size="small">
                <el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </div>
          </div>
        </div>
        <div class="fun-block">
          <div class="fun-title">
            批量操作

            <el-popover placement="top" :width="210" trigger="hover">
              <template #reference>
                <i class="iconfont icon-bangzhu"></i>
              </template>
              <div>
                <h4>内置变量</h4>
                <p>&nbsp;&nbsp;<b style="color: #409eff">[name]</b>: 表示原先文件名</p>
                <p>&nbsp;&nbsp;<b style="color: #409eff">[ext]</b>: 表示原先文件后缀名</p>
                <p>&nbsp;&nbsp;<b style="color: #ff584c">支持JavaScript表达式!!!</b></p>
              </div>
            </el-popover>
          </div>

          <el-input placeholder="请输入重命名的内容" size="default" v-model="operParam.input"> </el-input>
          <el-button
            type="primary"
            size="default"
            :disabled="!selectFile.length || !operParam.input"
            @click="handleRename"
          >
            <i class="iconfont icon-SQLcheck-o"></i>
            &nbsp; 重命名
          </el-button>

          <div class="menu">
            <div class="menu-item">
              <el-button type="danger" size="small" :disabled="!selectFile.length" @click="handleRemove"
                >删除选中的文件</el-button
              >
            </div>
          </div>
        </div>

        <div class="history">
          <div class="history-title">操作记录</div>
          <div class="history-content">
            <FileOperHistory :historys="historys" />
          </div>
        </div>
      </div>
    </div>

    <EnvPage />
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive } from "vue";
import { ElMessageBox } from "element-plus";
import { message } from "@/utils/Element";
import { invoke } from "@tauri-apps/api/tauri";
import { open as dialogOpen } from "@tauri-apps/api/dialog";
import { open as shellOpen } from "@tauri-apps/api/shell";
import { convertObjKey } from "./util";
import { typeList } from "./config";

import type { FileInfoType } from "./components/FileTable.vue";
import type { FileOperHistoryType } from "./components/FileOperHistory.vue";

// 正则语法: https://docs.rs/regex/latest/regex/#syntax

const sep = "\\";
const contentLoading = ref(false);

// 查询操作参数
const queryParam = reactive({
  selectPath: "C:\\Users\\33153\\Desktop\\hello-test",
  input: ".rs$",
  isDeep: false,
  isReg: true,
  searchType: "ALL"
});

// 批量操作参数
const operParam = reactive({
  input: `if (Number(name) > 5) "123-" + name + ext`
  // input: `"test" + name + ext`,
});

// 查询到的文件
const files = ref<Array<FileInfoType>>([]);
// 当前选中的文件
const selectFile = ref<Array<FileInfoType>>([]);
// TODO 操作历史记录
const historys = ref<Array<any>>([]);

// 打开目录
const openDir = async () => {
  const selected = await dialogOpen({
    directory: true,
    defaultPath: queryParam.selectPath
  });

  if (typeof selected === "string") {
    queryParam.selectPath = selected;

    // 默认查找选择目录下面的文件
    handleDblClickPath({
      isDir: true,
      isFile: false,
      path: selected
    });
  }
};

// 搜索
const search = async () => {
  try {
    contentLoading.value = true;
    // 转换格式为 snakeCase
    const invokeParams = convertObjKey(queryParam, "snakeCase");

    console.log("查询参数: ", invokeParams);

    const res: any[] = await invoke("search_path", { invokeParams });
    // 转换格式为 camelize
    const fileData = res.map(e => convertObjKey(e, "camelize"));
    files.value = fileData;
    if (fileData.length === 0) message.warning("没有查询到文件");

    console.log("查询结果: ", fileData);
  } catch (error) {
    console.log("error: ", error);
    message.error(error as string);
  } finally {
    contentLoading.value = false;
  }
};

// 选择
const handleSelectionChange = (val: Array<FileInfoType>) => {
  selectFile.value = val;
};

// 双击路径, 如果是目录则查询其下面的所有文件
const handleDblClickPath = (row: FileInfoType) => {
  if (row.isDir) {
    queryParam.selectPath = row.path;
    queryParam.isDeep = false;
    queryParam.searchType = "ALL";
    queryParam.input = ""; // 查询所有
    search();
  }
};

// 上一级
const backPrevPath = () => {
  const curPath = queryParam.selectPath.replace(/\//g, sep);
  // 上一级
  const prevPath = curPath.split(sep).slice(0, -1).join(sep);

  if (prevPath.endsWith(":")) {
    message.warning("TODO 已经到根盘符");
    return;
  }

  handleDblClickPath({ isDir: true, isFile: false, path: prevPath });
};

// 重命名
const handleRename = async () => {
  try {
    contentLoading.value = true;

    // 构建参数
    const invokeParams = selectFile.value
      .map(e => {
        let result: [string, string];
        const paths = e.path.replace(/\//g, sep).split(sep);
        const file = paths.pop();
        const dir = paths.join(sep);
        if (file) {
          const [name, _ext] = file.split(".");
          const ext = `.${_ext}`;
          // 解析输入为js表达式
          const rename = eval(operParam.input);
          if (rename) {
            result = [e.path, dir + sep + rename];
          } else {
            result = [e.path, ""];
          }
        } else {
          result = [e.path, ""];
        }
        return result;
      })
      .filter(e => e[1]);

    console.log("重命名参数: ", invokeParams);
    const res: Array<FileOperHistoryType> = await invoke("rename_files", { invokeParams });
    handleAfter(res);
  } catch (error) {
    console.log("error: ", error);
    message.error(error as string);
  } finally {
    contentLoading.value = false;
  }
};

// 删除
const handleRemove = () => {
  ElMessageBox.confirm("确定要删除选中的文件吗?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(async () => {
      try {
        contentLoading.value = true;
        const invokeParams = selectFile.value.map(e => e.path);
        const res: Array<FileOperHistoryType> = await invoke("remove_files", { invokeParams });
        handleAfter(res);
      } catch (error) {
        console.log("error: ", error);
        message.error(error as string);
      } finally {
        contentLoading.value = false;
      }
    })
    .catch(() => {});
};

const handleAfter = (res: Array<FileOperHistoryType>) => {
  console.log("handleAfter: ", res);
  // 添加历史记录
  const history = res.map(e => convertObjKey(e, "camelize"));
  historys.value.push(...history);
  // 刷新到当前的目录信息
  search();
};
</script>

<style lang="scss" scoped>
@import "@/styles/var.scss";

.wrapper {
  width: 100%;
  height: calc(100vh - 130px);

  .title {
    height: 40px;
    // background: green;
    display: flex;
    align-items: center;

    .iconfont {
      font-size: 28px;
      padding: 0 4px;
      cursor: pointer;
      border-radius: 2px;
      transition: all 0.3s;
      margin-right: 4px;

      &:hover {
        color: white;
        background: #ccc;
      }
    }

    .path {
      font-size: 18px;
      cursor: pointer;
    }
  }

  .content {
    height: calc(100% - 40px);
    display: flex;
    $marginR: 10px;

    .left {
      flex: 1;
      border: 1px solid #ccc;
      padding: 0 4px;
      margin-right: 10px;
      overflow: auto;
    }
    .right {
      flex: 1;
      border: 1px solid #ccc;

      .fun-block {
        padding: 10px;
        border-bottom: 1px solid green;

        :deep(.el-input) {
          width: calc(100% - 120px);
          margin: 6px 0 6px $marginR;
          margin-right: 10px;
        }

        .menu {
          margin-left: $marginR;
          display: flex;
          align-items: center;

          .menu-item {
            margin-right: 12px;

            span {
              font-size: 12px;
            }
            :deep(.el-select) {
              .el-input {
                margin: 0;
              }
            }
            .iconfont {
              font-size: 14px;
              margin-left: 4px;
              cursor: pointer;

              &:hover {
                opacity: 0.8;
              }
            }
          }
        }
      }

      .fun-title,
      .history-title {
        font-size: 14px;
        height: 20px;
        font-weight: bold;
        margin-bottom: 6px;
      }

      .history {
        height: calc(100vh - 460px);
        padding: 10px;

        .history-content {
          height: calc(100% - 20px);
          margin-left: $marginR;
          overflow: auto;
        }
      }
    }
  }
}
</style>
